package com.mysoft.gfyx.clue.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mysoft.framework.common.exception.BusinessLogicException;
import com.mysoft.framework.common.user.User;
import com.mysoft.framework.common.util.MappingUtil;
import com.mysoft.framework.context.api.ContextManager;
import com.mysoft.framework.context.info.ContextInfo;
import com.mysoft.framework.sdk.system.api.MessagePush;
import com.mysoft.framework.sdk.system.api.SystemDataProvider;
import com.mysoft.framework.sdk.system.dto.MessagePushDTO;
import com.mysoft.framework.sdk.system.dto.UserDTO;
import com.mysoft.gfyx.clue.backgroundjob.SubscriptionJobHandler;
import com.mysoft.gfyx.clue.controller.dto.GetLatestOpportunitiesResponseDto;
import com.mysoft.gfyx.clue.controller.dto.MySubscriptionPageDto;
import com.mysoft.gfyx.clue.controller.dto.Subscription.AddProjectSubscriptionRequestDto;
import com.mysoft.gfyx.clue.controller.dto.Subscription.AddRadarSubscriptionRequestDto;
import com.mysoft.gfyx.clue.controller.dto.Subscription.AddSubscriptionRequestDto;
import com.mysoft.gfyx.clue.controller.dto.Subscription.GetWxQrCodeRequestDto;
import com.mysoft.gfyx.clue.dao.*;
import com.mysoft.gfyx.clue.dao.dto.OpSubscriptionDataDto;
import com.mysoft.gfyx.clue.dao.dto.ProjectSubscriptionDataDto;
import com.mysoft.gfyx.clue.dao.entity.*;
import com.mysoft.framework.core.function.authorization.AuthenticationUser;
import com.mysoft.framework.modeling.dto.*;
import com.mysoft.framework.mybaits.extension.ExtensionLoadDataHelper;
import com.mysoft.gfyx.clue.dao.ClueFeedDao;
import com.mysoft.gfyx.clue.dao.FeedConfigDao;
import com.mysoft.gfyx.clue.dao.SubscriptionConfigDao;
import com.mysoft.gfyx.clue.dao.entity.ClueFeed;
import com.mysoft.gfyx.clue.dao.entity.FeedConfig;
import com.mysoft.gfyx.clue.dao.entity.SubscriptionConfig;
import com.mysoft.gfyx.clue.mip.MipCustomerService;
import com.mysoft.gfyx.clue.mip.OpSubscriptionService;
import com.mysoft.gfyx.clue.mip.dto.OpSubscriptionRequestDto;
import com.mysoft.gfyx.clue.mip.OpptySubsSearchService;
import com.mysoft.gfyx.clue.mip.dto.*;
import com.mysoft.gfyx.clue.remoteservice.RemoteAreaService;
import com.mysoft.gfyx.clue.remoteservice.RemoteProfitService;
import com.mysoft.gfyx.clue.remoteservice.RemoteSystemService;
import com.mysoft.gfyx.clue.remoteservice.dto.*;
import com.mysoft.gfyx.clue.service.AreaOptionService;
import com.mysoft.gfyx.clue.service.MessageInboxService;
import com.mysoft.gfyx.clue.service.NewUserService;
import com.mysoft.gfyx.clue.service.SubscriptionService;
import com.mysoft.gfyx.clue.service.dto.*;
import com.mysoft.gfyx.common.dto.TotalDto;
import com.mysoft.gfyx.common.message.EmailHelper;
import com.mysoft.gfyx.common.message.dto.CommonSendPushOrderRequestDto;
import com.mysoft.gfyx.common.rpc.opensearch.OpensearchClientFactoryService;
import com.mysoft.gfyx.common.rpc.opensearch.OpensearchClientService;
import com.mysoft.gfyx.common.rpc.opensearch.dto.*;
import com.mysoft.gfyx.common.table.LoadDataApiServiceHelper;
import com.mysoft.gfyx.common.time.TimeService;
import com.mysoft.gfyx.common.util.LogUtil;
import com.mysoft.gfyx.common.util.MyStringUtil;
import com.mysoft.gfyx.common.util.OpportunityUtil;
import com.mysoft.gfyx.common.util.PageUtil;
import com.mysoft.gfyx.common.ycg.YcgFileService;
import com.mysoft.sdk.context.core.ThreadContextHolder;
import com.mysoft.sdk.job.core.adapter.XxlJobHandlerAdapter;
import com.mysoft.sdk.job.core.api.admin.MysoftJobClient;
import com.mysoft.sdk.job.core.api.admin.MysoftJobInfoDTO;
import com.mysoft.sdk.job.core.handler.MethodMysoftJobHandler;
import com.xxl.job.core.executor.XxlJobExecutor;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;


import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SubscriptionServiceImp implements SubscriptionService {

    @Autowired
    private SubscriptionConfigDao subscriptionConfigDao;

    @Autowired
    private ProjectSubscriptionConfigDao projectSubscriptionConfigDao;

    @Autowired
    private RadarSubscriptionConfigDao radarSubscriptionConfigDao;

    @Autowired
    private RadarSubscriptionPushLogDao radarSubscriptionPushLogDao;

    @Autowired
    private FeedConfigDao feedConfigDao;

    @Autowired
    private ClueFeedDao clueFeedDao;

    @Autowired
    private OpSubscriptionDao opSubscriptionDao;

    @Autowired
    private UserWxBindDao userWxBindDao;

    @Autowired
    private ProjectSubscriptionDao projectSubscriptionDao;
    @Autowired
    AreaOptionService areaOptionService;
    @Resource
    private ContextManager contextManager;

    @Autowired
    private MysoftJobClient mysoftJobClient;

    @Autowired
    private TimeService timeService;

    @Autowired
    private MipCustomerService mipCustomerService;

    @Autowired
    private OpSubscriptionService opSubscriptionService;

    @Autowired
    private OpptySubsSearchService opptySubsSearchService;

    @Autowired
    private RemoteProfitService remoteProfitService;

    @Autowired
    private RemoteAreaService remoteAreaService;

    @Resource
    private MessagePush messagePush;

    @Resource
    private LoadDataApiServiceHelper loadDataApiServiceHelper;

    @Resource
    private YcgFileService ycgFileService;

    @Autowired
    private RemoteSystemService remoteSystemService;

    @Autowired
    private Environment environment;

    @Autowired
    private PageUtil pageUtil;

    @Autowired
    private OpportunityUtil opportunityUtil;

    @Autowired
    private OpensearchClientFactoryService opensearchClientFactoryService;

    @Autowired
    private LogUtil logUtil;

    @Autowired
    private SystemDataProvider systemDataProvider;

    @Autowired
    private SubscriptionJobHandler subscriptionJobHandler;

    @Autowired
    private MessageInboxService messageInboxService;

    @Autowired
    private NewUserService gfyxUserService;

    @Value("${gfyx.host}")
    private String GFYXHost;

    public boolean applyCron() {
        // 首先判断调度是否启用
        if (!checkJobExist()) {
            String tenantCode = contextManager.fetchContextInfo().getTenantCode();

            String realJobHandlerName = "SubscriptionJobHandler_tenant_" + tenantCode;
            MysoftJobInfoDTO jobInfoDTO = new MysoftJobInfoDTO();
            jobInfoDTO.setJobGroupName("gfyx");
            jobInfoDTO.setExecutorHandler(realJobHandlerName);
            jobInfoDTO.setJobDesc("客户管理调度");
            jobInfoDTO.setScheduleConf("0 0,30 */1 * * ?");

            Integer jobId = mysoftJobClient.createAndStart(jobInfoDTO);

            // 判断监听是否存在
            if (XxlJobExecutor.loadJobHandler(realJobHandlerName) == null) {
                try {
                    // 组装jobHandler
                    MethodMysoftJobHandler jobHandler = new MethodMysoftJobHandler(subscriptionJobHandler, SubscriptionJobHandler.class.getMethod("execute"), null, null);
                    // 注册租户监听
                    XxlJobExecutor.registJobHandler(realJobHandlerName, new XxlJobHandlerAdapter(jobHandler, realJobHandlerName, tenantCode));
                } catch (NoSuchMethodException e) {
                    logUtil.error("注册xxl-job监听", e);
                }
            }

            if (jobId == null) {
                throw new BusinessLogicException("开启调度失败，请联系管理员解决");
            }
        }

        // 为每个用户创建一个永不执行或者每天执行的job，防止多次开启调度
        insertNeverExecuteFeed();
        insertNeverExecuteSubscription();
        insertNeverExecuteProjectSubscription();
        //已换表，废气
        //insertDailyExecuteRadarSubscriptionConfig();

        return true;
    }

    protected boolean checkJobExist() {
        //  由于不支持检查job是否存在，所以采用查表的形式。当订阅和feed表都没有配置，则建立一个调度
        QueryWrapper<SubscriptionConfig> queryWrapperS = new QueryWrapper<>();
        int subscriptionCount = subscriptionConfigDao.selectCount(queryWrapperS).intValue();

        QueryWrapper<FeedConfig> queryWrapperF = new QueryWrapper<>();
        int feedCount = feedConfigDao.selectCount(queryWrapperF).intValue();

        return (subscriptionCount + feedCount) > 0;
    }

    protected void insertNeverExecuteFeed() {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        QueryWrapper<FeedConfig> queryWrapperF = new QueryWrapper<>();
        queryWrapperF.eq("FeedConfigGUID", authenticationUser.getUserId());
        int feedCount = feedConfigDao.selectCount(queryWrapperF).intValue();

        if (feedCount <= 0) {
            FeedConfig feedConfig = new FeedConfig();
            feedConfig.setFeedConfigGUID(authenticationUser.getUserId());
            feedConfig.setIsEmailSendingOpened(0);
            feedConfig.setIsSiteMessageSendingOpened(1);
            feedConfig.setLandArea("0");
            feedConfig.setProjectArea("0");
            feedConfig.setIsSendingLand(1);
            feedConfig.setIsSendingProject(1);
            feedConfig.setSendingTime("08:00");
            feedConfig.setPeriod(SubscriptionService.PERIOD_DAILY);
            feedConfigDao.insert(feedConfig);
        }
    }

    protected void insertNeverExecuteSubscription() {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        QueryWrapper<SubscriptionConfig> queryWrapperS = new QueryWrapper<>();
        queryWrapperS.eq("SubscriptionConfigGUID", authenticationUser.getUserId());
        int subscriptionCount = subscriptionConfigDao.selectCount(queryWrapperS).intValue();

        if (subscriptionCount <= 0) {
            SubscriptionConfig subscriptionConfig = new SubscriptionConfig();
            subscriptionConfig.setSubscriptionConfigGUID(authenticationUser.getUserId());
            subscriptionConfig.setIsEmailSendingOpened(0);
            subscriptionConfig.setIsSiteMessageSendingOpened(1);
            subscriptionConfig.setArea("0");
            subscriptionConfig.setType("ycg_bid,ycg_recruit,website_bid,trading_center");
            subscriptionConfig.setSendingTime("08:00");
            subscriptionConfig.setPeriod(SubscriptionService.PERIOD_DAILY);
            subscriptionConfigDao.insert(subscriptionConfig);
        }
    }

    protected void insertNeverExecuteProjectSubscription() {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        QueryWrapper<ProjectSubscriptionConfig> queryWrapperP = new QueryWrapper<>();
        queryWrapperP.eq("ProjectSubscriptionConfigGUID", authenticationUser.getUserId());
        int projectSubscriptionCount = projectSubscriptionConfigDao.selectCount(queryWrapperP).intValue();

        if (projectSubscriptionCount <= 0) {
            ProjectSubscriptionConfig projectSubscriptionConfig = new ProjectSubscriptionConfig();
            projectSubscriptionConfig.setProjectSubscriptionConfigGUID(authenticationUser.getUserId());
            projectSubscriptionConfig.setIsEmailSendingOpened(0);
            projectSubscriptionConfig.setIsSiteMessageSendingOpened(1);
            projectSubscriptionConfig.setArea("0");
            projectSubscriptionConfig.setSendingTime("08:00");
            projectSubscriptionConfig.setPeriod(SubscriptionService.PERIOD_DAILY);
            projectSubscriptionConfig.setLandDateAfter(1);
            projectSubscriptionConfig.setCommenceDateAfter(1);
            projectSubscriptionConfigDao.insert(projectSubscriptionConfig);
        }
    }

    protected void insertDailyExecuteRadarSubscriptionConfig() {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        QueryWrapper<RadarSubscriptionConfig> queryWrapperP = new QueryWrapper<>();
        queryWrapperP.eq("RadarSubscriptionConfigGUID", authenticationUser.getUserId());
        int radarSubscriptionCount = radarSubscriptionConfigDao.selectCount(queryWrapperP).intValue();

        if (radarSubscriptionCount <= 0) {
            RadarSubscriptionConfig radarSubscriptionConfig = new RadarSubscriptionConfig();
            radarSubscriptionConfig.setRadarSubscriptionConfigGUID(authenticationUser.getUserId());
            radarSubscriptionConfig.setReceivedGUID(authenticationUser.getUserId());
            radarSubscriptionConfig.setReceivedName(authenticationUser.getUserName());
            radarSubscriptionConfig.setSendingTime("08:00");
            radarSubscriptionConfig.setPeriod(SubscriptionService.PERIOD_DAILY);
            radarSubscriptionConfigDao.insert(radarSubscriptionConfig);
        }
    }

    /**
     * 调各个定时器以完成任务，将数据插入到建模的业务表中
     *
     * @return
     */
    public boolean pull() {
        // 1.首先拉去客户动态的信息
        boolean pulledFeed = pullCustomerFeed();

        // 2.然后去拉商机订阅的信息，已关闭20230816
        //boolean pulledSubscription = pullOpportunitySubscription();

        // 3.然后去拉项目订阅的信息 ，已关闭20230816
        //boolean pulledProjectSubscription = pullProjectOpportunitySubscription();

        // 4 线索订阅,已重构至商机服务中,20230920
        //boolean pulledRadarSubscription = pullRadarSubscription();

        // 5 滚动删除历史的商机订阅
        deleteOldSubscription();

        return true;
    }

    protected boolean pullCustomerFeed() {
        QueryWrapper<FeedConfig> queryWrapperF = new QueryWrapper<>();
        queryWrapperF.ne("Period", SubscriptionService.PERIOD_NEVER);
        List<FeedConfig> feeds = feedConfigDao.selectList(queryWrapperF);

        feeds.forEach(f -> {
            try {
                // 是否到了拉取时间？
                if (!isTimeToPull(f.getPeriod(), f.getSendingTime(), f.getLastSentTime())) {
                    return;
                }

                // 拉去用户的客户动态
                InsertFeedReturnDto pulled = pullUserCustomerFeed(f);

                // 发送消息
                sendCustomerFeedMessage(pulled, f);

                //更新上次执行时间
                markFeedPulled(f);
            } catch (Exception e) {
                logUtil.error("调度归属" + f.getCreatedName() + ",客户动态订阅执行失败", e);
            }
        });

        return true;
    }

    protected boolean sendCustomerFeedMessage(InsertFeedReturnDto feeds, FeedConfig config) {
        Iterator<ClueFeed> it = feeds.getList().iterator();
        int landCount = 0;
        int projectCount = 0;
        while (it.hasNext()) {
            ClueFeed s = it.next();
            if (s.getFeedType().equals(TYPE_LAND)) landCount++;
            if (s.getFeedType().equals(TYPE_PROJECT)) projectCount++;
        }
        if (landCount == 0 && projectCount == 0) {
            logUtil.info("客户动态调度:" + config.getCreatedName(), "动态数量为0，不发送信息");
            return false;
        }

        // 站内信
        MessagePushDTO dto = new MessagePushDTO();
        dto.setUserGuid(config.getCreatedGUID());
        dto.setWakeType("普通消息");
        dto.setWakeSubject("尊敬的用户，您关注的客户 ，新增拿地 " + landCount + " ，新增项目开盘 " + projectCount + "，请及时查看！");
        dto.setAppCode("4022");
        dto.setPageUrl("/std/40220902/08da9d38-94ef-49e9-8ef1-285042087089");
        dto.setBusinessGuid(UUID.randomUUID());
        dto.setBusinessType("客户动态");
        messagePush.sendToDo(dto);

        // 站内信同步到 新表
        MessageInboxDto messageDto = new MessageInboxDto();
        messageDto.setTitle("客户动态更新通知");
        messageDto.setMessageType("客户动态");
        messageDto.setContent(dto.getWakeSubject());
        messageDto.setLink(dto.getPageUrl());
        messageDto.setSenderId(gfyxUserService.GetAdminId());
        messageDto.setReceiverId(gfyxUserService.GetUserId(dto.getUserGuid().toString()));
        messageInboxService.AddMessage(messageDto);

        logUtil.info("客户动态调度:" + config.getCreatedName(), "站内信发送完成");
        // 邮件
        if (config.getIsEmailSendingOpened() != null && config.getIsEmailSendingOpened().equals(1)) {
            List<String> addresses = new ArrayList<String>() {{
                add(config.getEmail());
            }};
            String htmlContent = "<div>" + "尊敬的用户，您关注的客户 ，新增拿地 " + landCount + " ，新增项目开盘 " + projectCount + "，请及时<a href=\"" + GFYXHost + "/insight/customer/dynamic\">查看</a>！" + "</div>";
            htmlContent += "<ol>";
            Iterator<ClueFeed> itE = feeds.getList().iterator();
            while (itE.hasNext()) {
                ClueFeed s = itE.next();
                htmlContent += "<li>[" + s.getFeedType().toString() + "] " + s.getFeedTitle().toString() + "</li>";
            }
            htmlContent += "</ol>";
            //emailHelper.sendEmail(addresses, "客户动态", htmlContent);
            String sendPushOrder = environment.getProperty("sendmessage.subscription_push_order");
            sendEmail("客户动态", htmlContent, config.getEmail().toString(), sendPushOrder);
            logUtil.info("客户动态调度:" + config.getCreatedName(), "邮件发送完成");
        }

        return true;
    }

    protected boolean isTimeToPull(String period, String sendingTime, Date lastSentTime) {
        //  判断今天是否是拉数据的好日子
        if (!period.equals(SubscriptionService.PERIOD_DAILY)) {
            String[] weekDays = {"周日", "周一", "周二", "周三", "周四", "周五", "周六"};
            Calendar calendar = Calendar.getInstance();
            String weekday = weekDays[calendar.get(Calendar.DAY_OF_WEEK) - 1];

            if (!weekday.equals(period)) {
                return false;
            }
        }

        Date todayZero = timeService.getTodayZeroClock();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date now = new Date();
            Date sendingTimeDate = sdf.parse(sdfDate.format(now) + " " + sendingTime + ":00");

            // 判断上次发的日子是否早于今天
            if (lastSentTime != null && lastSentTime.getTime() > todayZero.getTime()) {
                return false;
            }
            // 判断是否到达了发送时间
            if (sendingTimeDate.getTime() > now.getTime()) {
                return false;
            }
        } catch (ParseException e) {
            return false;
        }

        return true;
    }

    protected boolean markFeedPulled(FeedConfig config) {
        Date date = new Date();
        config.setLastSentTime(date);
        feedConfigDao.updateById(config);
        return true;
    }

    protected InsertFeedReturnDto pullUserCustomerFeed(FeedConfig config) {
        CustomerFeedRequestDto customerFeedRequestDto = getPullUserCustomerFeedRequest(config);

        //customerFeedRequestDto.setTenant_code("ycg");
        //customerFeedRequestDto.setReceiver("08da73bf-27f1-440f-8b37-dcc53a3e3a0d");
        TjApiBaseRespondDto res = mipCustomerService.customerFeed(customerFeedRequestDto);
        InsertFeedReturnDto returnDs = new InsertFeedReturnDto();
        List<Map<String, String>> feed = res.getData();
        List<ClueFeed> insertTotal = new ArrayList<>();
        if (feed.size() > 0) {
            insertTotal = insertCustomerFeed(feed);
        }
        returnDs.setTotal(insertTotal.size());
        returnDs.setList(insertTotal);
        return returnDs;
    }

    protected CustomerFeedRequestDto getPullUserCustomerFeedRequest(FeedConfig config) {
        CustomerFeedRequestDto customerFeedRequestDto = new CustomerFeedRequestDto();

        if (config.getIsSendingLand() != null && config.getIsSendingLand() > 0) {
            customerFeedRequestDto.setGet_land(1);
            if (hasZeroInAreaField(config.getLandArea())) {
                customerFeedRequestDto.setGet_all_land(1);
            } else {
                customerFeedRequestDto.setLand_area(config.getLandArea());
            }
        }
        if (config.getIsSendingProject() != null && config.getIsSendingProject() > 0) {
            customerFeedRequestDto.setGet_project(1);
            if (hasZeroInAreaField(config.getProjectArea())) {
                customerFeedRequestDto.setGet_all_project(1);
            } else {
                customerFeedRequestDto.setProject_area(config.getProjectArea());
            }
        }

        customerFeedRequestDto.setTenant_code(contextManager.fetchContextInfo().getTenantCode());
        customerFeedRequestDto.setReceiver(config.getCreatedGUID().toString());

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if (config.getLastSentTime() == null) {
            Date createdTime = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24 * 7);
            customerFeedRequestDto.setCreated_time(sdf.format(createdTime));
        } else {
            customerFeedRequestDto.setCreated_time(sdf.format(config.getLastSentTime()));
        }


        return customerFeedRequestDto;
    }

    protected boolean hasZeroInAreaField(String area) {
        if (area == null) {
            return true;
        }
        String[] areas = area.split(",");
        for (String a : areas) {
            if (a.equals("0")) {
                return true;
            }
        }

        return false;
    }

    /**
     * 获取我的商机订阅数目
     *
     * @return 根据用户id 获取数量，如果查询为空，默认返回 0
     */
    public int getMySubscriptionCount() {
        ContextInfo contextInfo = contextManager.fetchContextInfo();
        UUID userId = contextInfo.getUserContext().getUserId();
        QueryWrapper<OpSubscription> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ReceiverGUID", userId);
        return opSubscriptionDao.selectCount(queryWrapper).intValue();
    }

    /**
     * 获取我的订阅客户动态
     *
     * @return 通过客户的招标，拿地，开盘数据相加
     */
    public int getMySubscriptionNewsCount() {
        ContextInfo contextInfo = contextManager.fetchContextInfo();
        UUID userId = contextInfo.getUserContext().getUserId();
        QueryWrapper<ClueFeed> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("ReceiverGUID", userId);
        return clueFeedDao.selectCount(queryWrapper).intValue();
    }

    /**
     * 是否开启商机订阅推送
     *
     * @return false 未开启 true 开启
     */
    public boolean isSetSubscriptionConfig() {
        ContextInfo contextInfo = contextManager.fetchContextInfo();
        UUID userId = contextInfo.getUserContext().getUserId();
        QueryWrapper<SubscriptionConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("CreatedGUID", userId);
        return (subscriptionConfigDao.selectCount(queryWrapper).intValue() > 0);
    }

    /**
     * 获取用户最新的商机数据
     *
     * @return 从数据表获取的商机数据
     */
    public MySubscriptionPageDto getLatestOpportunitiesList(Integer page, Integer pageSize) {
        ContextInfo contextInfo = contextManager.fetchContextInfo();
        UUID userId = contextInfo.getUserContext().getUserId();
        QueryWrapper<OpSubscription> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("OpSubscriptionGUID,Title,PublishTime,DeveloperName,OrganizingCode,SubscriptionUID,Source,Province,City,Tenderee,TendereeMobile,Deadline").eq("ReceiverGUID", userId).orderByDesc("PublishTime");
        Page<OpSubscription> opSubscriptions = opSubscriptionDao.selectPage(new Page<>(page, pageSize), queryWrapper);
        MySubscriptionPageDto response = new MySubscriptionPageDto();
        List<GetLatestOpportunitiesResponseDto> data = new ArrayList<>();
        response.setPage(page);
        response.setPageSize((int) opSubscriptions.getSize());
        if (opSubscriptions.getRecords() == null) {
            response.setTotal(0);
            response.setData(data);
            return response;
        }

        response.setTotal((int) opSubscriptions.getTotal());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        for (OpSubscription subscription : opSubscriptions.getRecords()) {
            GetLatestOpportunitiesResponseDto responseDto = new GetLatestOpportunitiesResponseDto();
            // 设置变量
            responseDto.setOpSubscriptionGUID(subscription.getOpSubscriptionGUID());
            responseDto.setTitle(subscription.getTitle());
            responseDto.setDeveloperName(subscription.getDeveloperName());
            responseDto.setSubscriptionUID(subscription.getSubscriptionUID());
            responseDto.setSource(subscription.getSource());
            responseDto.setLicenseCode(subscription.getOrganizingCode());
            Date publishTime = subscription.getPublishTime();
            if (publishTime != null) {
                responseDto.setPublishTime(sdf.format(publishTime));
            } else {
                responseDto.setPublishTime("");
            }
            responseDto.setMobile(subscription.getTendereeMobile());
            responseDto.setContact(subscription.getTenderee());
            responseDto.setServiceCategory(subscription.getBiddingServiceCategory());
            responseDto.setType(subscription.getSource());
            responseDto.setProvince(subscription.getProvince());
            responseDto.setCity(subscription.getCity());
            responseDto.setDeveloperLogo(subscription.getDeveloperLogo());
            responseDto.setDeveloperId(subscription.getDeveloperId());
            String endTime = "";
            if (subscription.getDeadline() != null) {
                endTime = subscription.getDeadline().toString();
            }
            responseDto.setStatus(opportunityUtil.getStatusFromEndTime(endTime));
            // 加入返回参数
            data.add(responseDto);
        }
        response.setData(data);
        return response;
    }

    /**
     * 从商机接口获取最新的商机数据
     *
     * @return 从接口获取的商机数据
     */
    public List<GetLatestOpportunitiesResponseDto> getLatestOpportunitiesListByApi() {
        //todo 待实现远程调用
        List<GetLatestOpportunitiesResponseDto> response = new ArrayList<>();
        return response;
    }

    protected List<ClueFeed> insertCustomerFeed(List<Map<String, String>> feed) {
        List<ClueFeed> clueFeeds = new LinkedList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        feed.forEach(f -> {
            QueryWrapper<ClueFeed> queryWrapperF = new QueryWrapper<>();
            queryWrapperF.eq("FeedUID", f.get("id"));
            queryWrapperF.eq("ReceiverGUID", UUID.fromString(f.get("receiver")));
            long existRecord = clueFeedDao.selectCount(queryWrapperF);
            if (existRecord > 0) {
                return;
            }

            ClueFeed clueFeed = new ClueFeed();
            clueFeed.setClueFeedGUID(UUID.randomUUID());
            clueFeed.setFeedUID(f.get("id"));
            clueFeed.setFeedID(f.get("feed_id"));
            try {
                if (f.get("feed_time") != null) clueFeed.setFeedTime(sdf.parse(f.get("feed_time")));
            } catch (java.text.ParseException ignored) {
            }
            clueFeed.setCity(f.get("city"));
            clueFeed.setCityCode(f.get("city_code"));
            clueFeed.setProvince(f.get("province"));
            clueFeed.setProvinceCode(f.get("province_code"));
            clueFeed.setFeedType(f.get("feed_type"));
            clueFeed.setFeedTitle(f.get("feed_title"));
            try {
                if (f.get("created_time") != null) clueFeed.setFeedCreatedTime(sdf.parse(f.get("created_time")));
            } catch (java.text.ParseException e) {
            }
            clueFeed.setCompanyTypeLabel(f.get("company_type_label"));
            clueFeed.setDeveloperName(f.get("developer_name"));
            clueFeed.setOrganizingCode(f.get("organizing_code"));
            clueFeed.setReceiverGUID(UUID.fromString(f.get("receiver")));
            clueFeed.setRelatedDeveloperName(f.get("related_developer_name"));
            clueFeed.setRelatedOrganizingCode(f.get("related_organizing_code"));

            clueFeeds.add(clueFeed);
        });
        if (clueFeeds.size() > 0) clueFeedDao.insertBatchWithDynamicExt(clueFeeds);
        return clueFeeds;
    }

    protected boolean pullOpportunitySubscription() {
        QueryWrapper<SubscriptionConfig> queryWrapperF = new QueryWrapper<>();
        queryWrapperF.ne("Period", SubscriptionService.PERIOD_NEVER);
        List<SubscriptionConfig> feeds = subscriptionConfigDao.selectList(queryWrapperF);

        feeds.forEach(f -> {
            try {
                // 是否到了拉取时间？
                if (!isTimeToPull(f.getPeriod(), f.getSendingTime(), f.getLastSentTime())) {
                    return;
                }

                // 拉去用户的客户动态
                InsertSubscriptionReturnDto res = pullUserSubscription(f);

                // 发送消息
                if (res.getTotal() > 0) {
                    logUtil.info("商机订阅调度:" + f.getCreatedName(), "订阅数量" + res.getTotal() + "条，开始发送消息");
                    sendSubscriptionMessage(res, f);
                } else {
                    logUtil.info("商机订阅调度:" + f.getCreatedName(), "订阅数量为0，无法发送消息");
                }
                //更新上次执行时间
                markSubscriptionPulled(f);

            } catch (Exception e) {
                logUtil.error("调度归属" + f.getCreatedName() + ",商机订阅执行失败", e);
            }
        });
        return true;
    }

    protected void deleteOldSubscription() {
        QueryWrapper<OpSubscription> queryWrapperF = new QueryWrapper<>();
        Date d = timeService.getDateAfter(-30, new Date());
        queryWrapperF.lt("createdTime", d);
        opSubscriptionDao.delete(queryWrapperF);

        QueryWrapper<ClueFeed> queryWrapper = new QueryWrapper<>();
        queryWrapper.lt("createdTime", d);
        clueFeedDao.delete(queryWrapper);

        QueryWrapper<ProjectSubscription> queryWrapperP = new QueryWrapper<>();
        queryWrapperP.lt("createdTime", d);
        projectSubscriptionDao.delete(queryWrapperP);
    }

    protected boolean pullProjectOpportunitySubscription() {
        QueryWrapper<ProjectSubscriptionConfig> queryWrapperF = new QueryWrapper<>();
        queryWrapperF.ne("Period", SubscriptionService.PERIOD_NEVER);
        List<ProjectSubscriptionConfig> feeds = projectSubscriptionConfigDao.selectList(queryWrapperF);

        feeds.forEach(f -> {
            try {
                // 是否到了拉取时间？
                if (!isTimeToPull(f.getPeriod(), f.getSendingTime(), f.getLastSentTime())) {
                    return;
                }

                // 拉去用户的客户动态
                InsertProjectSubscriptionReturnDto res = pullUserProjectSubscription(f);

                // 发送消息
                if (res.getTotal() > 0) {
                    logUtil.info("项目订阅调度:" + f.getCreatedName(), "订阅数量" + res.getTotal() + "条，开始发送消息");
                    sendProjectSubscriptionMessage(res, f);
                } else {
                    logUtil.info("项目订阅调度:" + f.getCreatedName(), "订阅数量为0，无法发送消息");
                }
                //更新上次执行时间
                markProjectSubscriptionPulled(f);
            } catch (Exception e) {
                logUtil.error("调度归属" + f.getCreatedName() + ",项目订阅执行失败", e);
            }
        });
        return true;
    }

    protected boolean pullRadarSubscription() {
        QueryWrapper<RadarSubscriptionConfig> queryWrapperF = new QueryWrapper<>();
        queryWrapperF.ne("Period", SubscriptionService.PERIOD_NEVER);
        List<RadarSubscriptionConfig> feeds = radarSubscriptionConfigDao.selectList(queryWrapperF);

        feeds.forEach(f -> {
            try {
                Thread.sleep(10000);
            } catch (InterruptedException e) {
                logUtil.error("调度休眠5s,err:", e);
            }

            try {
                // 是否到了拉取时间？
                if (!isTimeToPull(f.getPeriod(), f.getSendingTime(), f.getLastSentTime())) {
                    return;
                }

                // 拉取线索订阅数据
                PullRadarSubscriptionReturnDto res = pullRadarSubscription(f);

                // 发送消息
                if (res.getTotal() > 0) {
                    logUtil.info("线索订阅调度:" + f.getCreatedName(), "订阅数量" + res.getTotal() + "条，开始发送消息");
                    sendRadarSubscriptionMessage(res, f);
                } else {
                    logUtil.info("线索订阅调度:" + f.getCreatedName(), "订阅数量为0，无法发送消息");
                }
                //更新上次执行时间
                markRadarSubscriptionPulled(f);
            } catch (Exception e) {
                logUtil.error("调度归属" + f.getReceivedName() + ",线索订阅执行失败", e);
            }

        });
        return true;
    }


    protected boolean markSubscriptionPulled(SubscriptionConfig config) {
        Date date = new Date();
        config.setLastSentTime(date);
        subscriptionConfigDao.updateById(config);
        return true;
    }

    protected boolean markProjectSubscriptionPulled(ProjectSubscriptionConfig config) {
        Date date = new Date();
        config.setLastSentTime(date);
        projectSubscriptionConfigDao.updateById(config);
        return true;
    }

    protected boolean markRadarSubscriptionPulled(RadarSubscriptionConfig config) {
        Date date = new Date();
        config.setLastSentTime(date);
        radarSubscriptionConfigDao.updateById(config);
        return true;
    }

    protected InsertSubscriptionReturnDto pullUserSubscription(SubscriptionConfig config) {
        if (config.getCompanyType() == null || config.getCompanyType().equals("")) {//如果没有设置订阅，则退出
            return new InsertSubscriptionReturnDto();
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date createdTime;
        if (config.getLastSentTime() == null) {
            createdTime = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24 * 7);
        } else {
            createdTime = config.getLastSentTime();
        }

        int page = 1;
        int pageSize = 500;
        String area = config.getArea();
        if (hasZeroInAreaField(config.getArea())) {
            area = "";
        }

        float purchaseAmountMinF = config.getPurchaseAmountMin() == null ? 0 : config.getPurchaseAmountMin() * 10000;//金额单位，万元转为元
        float purchaseAmountMaxF = config.getPurchaseAmountMax() == null ? 0 : config.getPurchaseAmountMax() * 10000;//金额单位，万元转为元
        String purchaseAmountMin = purchaseAmountMinF == 0 ? "" : Float.toString(purchaseAmountMinF);
        String purchaseAmountMax = purchaseAmountMaxF == 0 ? "" : Float.toString(purchaseAmountMaxF);
        area = filterProvinceProfit(area);
        EsBasePagerRespondDto res = opptySubsSearchService.pullSubscription(config.getKeyword(), area, config.getType(), sdf.format(createdTime), config.getCompanyType(), purchaseAmountMin, purchaseAmountMax, config.getPhoneType(), page, pageSize);

        EsBasePagerRespondDto.DataSet ds = res.getData();

        InsertSubscriptionReturnDto returnDS = new InsertSubscriptionReturnDto();
        List<OpSubscription> totalInserted = insertSubscription(ds.getList(), config.getCreatedGUID().toString());
        returnDS.setList(totalInserted);
        returnDS.setTotal(totalInserted.size());
        return returnDS;
    }

    public String filterProvinceProfit(String area) {
        if (area == null || area.equals("")) {
            return area;
        }

        HashSet<String> provinceAndCityCodeList = new HashSet<>();
        //获取有权限和权益的省市code
        List<OptionItem> areaList = areaOptionService.getProfitWithPermissionAreaData();
        if (areaList != null && areaList.size() > 0) {
            areaList.forEach(item -> {
                provinceAndCityCodeList.add(item.getValue());
            });
        }

        List<String> areaCodeList = Arrays.asList(area.split(","));
        List<String> areaCodeListNew = new ArrayList<>();
        //判断设置的省市code是否有权限
        areaCodeList.forEach(p -> {
            if (provinceAndCityCodeList.contains(p)) {
                areaCodeListNew.add(p);
            }
        });
        return areaCodeListNew.stream().map(String::valueOf).collect(Collectors.joining(","));
    }

    protected InsertProjectSubscriptionReturnDto pullUserProjectSubscription(ProjectSubscriptionConfig config) {
        if (config.getLandType() == null || config.getLandType().equals("")) {//如果没有设置订阅，则退出
            return new InsertProjectSubscriptionReturnDto();
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date commenceDateAfter;
        if (config.getCommenceDateAfter() == null || config.getCommenceDateAfter().equals(0)) {
            commenceDateAfter = new Date();
        } else {
            commenceDateAfter = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24 * config.getCommenceDateAfter());
        }

        Date landDateAfter;
        if (config.getLandDateAfter() == null || config.getLandDateAfter().equals(0)) {
            landDateAfter = new Date();
        } else {
            landDateAfter = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24 * config.getLandDateAfter());
        }

        int page = 1;
        int pageSize = 500;
        String area = config.getArea();
        if (hasZeroInAreaField(config.getArea())) {
            area = "";
        }
        area = filterProvinceProfit(area);
        EsBasePagerRespondDto res = opptySubsSearchService.pullProjectSubscription(area, config.getLandType(), config.getLandPriceMin(), config.getLandPriceMax(), config.getProjectLabel(), sdf.format(commenceDateAfter), sdf.format(landDateAfter), page, pageSize);

        EsBasePagerRespondDto.DataSet ds = res.getData();

        InsertProjectSubscriptionReturnDto returnDS = new InsertProjectSubscriptionReturnDto();
        List<ProjectSubscription> totalInserted = insertProjectSubscription(ds.getList(), config.getCreatedGUID().toString());
        returnDS.setList(totalInserted);
        returnDS.setTotal(totalInserted.size());
        return returnDS;
    }


    protected PullRadarSubscriptionReturnDto pullRadarSubscription(RadarSubscriptionConfig config) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date createdTime;
        if (config.getLastSentTime() == null) {
            createdTime = new Date(System.currentTimeMillis() - 1000 * 60 * 60 * 24 * 7);
        } else {
            createdTime = config.getLastSentTime();
        }
        String createdTimeStr = sdf.format(createdTime);
        int page = 1;
        int pageSize = 100;
        String area = config.getArea();
        if (hasZeroInAreaField(config.getArea())) {
            area = "";
        }
        area = filterProvinceProfit(area);


        // todo 修改获取城市数据
        OpensearchClientService service = opensearchClientFactoryService.getOpensearchService();

        SearchTakeLandRequestDto searchTakeLandRequestDto = new SearchTakeLandRequestDto();
        searchTakeLandRequestDto.setKeyword(config.getProjectKeywords());
        searchTakeLandRequestDto.setLand_type(config.getLandUsage());
        searchTakeLandRequestDto.setIs_price_gt_avg(config.getProjectTag());
        searchTakeLandRequestDto.setArea(area);
        searchTakeLandRequestDto.setCreated_time(createdTimeStr);
        searchTakeLandRequestDto.setPage(page);
        searchTakeLandRequestDto.setPage_size(pageSize);
        OpenSearchListResponseDto resTakenLand = service.searchTakenLand(searchTakeLandRequestDto);

        SearchMohurdProjectRequestDto searchMohurdProjectRequestDto = new SearchMohurdProjectRequestDto();
        searchMohurdProjectRequestDto.setKeyword(config.getProjectKeywords());
        searchMohurdProjectRequestDto.setIs_price_gt_avg(config.getProjectTag());
        searchMohurdProjectRequestDto.setPrj_type_num(config.getProjectType());
        searchMohurdProjectRequestDto.setArea(area);
        searchMohurdProjectRequestDto.setCreated_time(createdTimeStr);
        searchMohurdProjectRequestDto.setPage(page);
        searchMohurdProjectRequestDto.setPage_size(pageSize);
        OpenSearchListResponseDto resMohurdProject = service.searchMohurdProject(searchMohurdProjectRequestDto);

        SearchProjectRequestDto searchProjectRequestDto = new SearchProjectRequestDto();
        searchProjectRequestDto.setKeyword(config.getProjectKeywords());
        searchProjectRequestDto.setFitment_fee_label(config.getFitmentType());
        searchProjectRequestDto.setIs_price_gt_avg(config.getProjectTag());
        searchProjectRequestDto.setArea(area);
        searchProjectRequestDto.setCreated_time(createdTimeStr);
        searchProjectRequestDto.setPage(page);
        searchProjectRequestDto.setPage_size(pageSize);
        OpenSearchListResponseDto resProject = service.searchProject(searchProjectRequestDto);

        PurchaseSubscriptionRequestDto purchaseSubscriptionRequestDto = new PurchaseSubscriptionRequestDto();
        purchaseSubscriptionRequestDto.setKeyword(config.getBidKeywords());
        purchaseSubscriptionRequestDto.setArea(area);
        purchaseSubscriptionRequestDto.setCreated_time(createdTimeStr);
        purchaseSubscriptionRequestDto.setPage(page);
        purchaseSubscriptionRequestDto.setPage_size(pageSize);
        OpenSearchListResponseDto resPurchase = service.purchaseSubscription(purchaseSubscriptionRequestDto);

        SearchSupplierRequestDto searchSupplierRequestDto = new SearchSupplierRequestDto();
        searchSupplierRequestDto.setKeyword(config.getBidKeywords());
        searchSupplierRequestDto.setArea(area);
        searchSupplierRequestDto.setCreated_time(createdTimeStr);
        searchSupplierRequestDto.setPage(page);
        searchSupplierRequestDto.setPage_size(pageSize);
        OpenSearchListResponseDto resSupplier = service.searchSupplier(searchSupplierRequestDto);
        PullRadarSubscriptionReturnDto pullRadarSubscriptionReturnDto = new PullRadarSubscriptionReturnDto();
        //数据
        List<PullRadarSubscriptionReturnDto.RadarData> landList = new ArrayList<>();

        resTakenLand.getData().getList().forEach(p -> {
            if (landList.size() < 10) {
                PullRadarSubscriptionReturnDto.RadarData radarData = new PullRadarSubscriptionReturnDto.RadarData();
                radarData.setTitle(p.get("project_name").toString());
                landList.add(radarData);
            }
        });
        List<PullRadarSubscriptionReturnDto.RadarData> mohurdProjectList = new ArrayList<>();
        resMohurdProject.getData().getList().forEach(p -> {
            if (mohurdProjectList.size() < 10) {
                PullRadarSubscriptionReturnDto.RadarData radarData = new PullRadarSubscriptionReturnDto.RadarData();
                radarData.setTitle(p.get("prj_name").toString());
                mohurdProjectList.add(radarData);
            }
        });
        List<PullRadarSubscriptionReturnDto.RadarData> projectList = new ArrayList<>();
        resProject.getData().getList().forEach(p -> {
            if (projectList.size() < 10) {
                PullRadarSubscriptionReturnDto.RadarData radarData = new PullRadarSubscriptionReturnDto.RadarData();
                radarData.setTitle(p.get("project_title").toString());
                projectList.add(radarData);
            }
        });
        List<PullRadarSubscriptionReturnDto.RadarData> purchaseList = new ArrayList<>();
        resPurchase.getData().getList().forEach(p -> {
            if (purchaseList.size() < 10) {
                PullRadarSubscriptionReturnDto.RadarData radarData = new PullRadarSubscriptionReturnDto.RadarData();
                radarData.setTitle(p.get("title").toString());
                purchaseList.add(radarData);
            }
        });
        List<PullRadarSubscriptionReturnDto.RadarData> supplierList = new ArrayList<>();
        resSupplier.getData().getList().forEach(p -> {
            if (supplierList.size() < 10) {
                PullRadarSubscriptionReturnDto.RadarData radarData = new PullRadarSubscriptionReturnDto.RadarData();
                radarData.setTitle(p.get("supplier_name").toString());
                supplierList.add(radarData);
            }
        });

        //数量
        pullRadarSubscriptionReturnDto.setTotal(resTakenLand.getData().getTotal() + resMohurdProject.getData().getTotal() + resProject.getData().getTotal() + resPurchase.getData().getTotal() + resSupplier.getData().getTotal());
        pullRadarSubscriptionReturnDto.setLandTotal(resTakenLand.getData().getTotal());
        pullRadarSubscriptionReturnDto.setMohurdProjectTotal(resMohurdProject.getData().getTotal());
        pullRadarSubscriptionReturnDto.setProjectTotal(resProject.getData().getTotal());
        pullRadarSubscriptionReturnDto.setPurchaseTotal(resPurchase.getData().getTotal());
        pullRadarSubscriptionReturnDto.setSupplierTotal(resSupplier.getData().getTotal());
        pullRadarSubscriptionReturnDto.setLandList(landList);
        pullRadarSubscriptionReturnDto.setMohurdProjectList(mohurdProjectList);
        pullRadarSubscriptionReturnDto.setProjectList(projectList);
        pullRadarSubscriptionReturnDto.setPurchaseList(purchaseList);
        pullRadarSubscriptionReturnDto.setSupplierList(supplierList);
        logUtil.info("线索订阅调度:" + config.getCreatedName(), "土地数量" + resTakenLand.getData().getTotal() + "，在建项目数量" + resMohurdProject.getData().getTotal() + "，在售项目数量" + resProject.getData().getTotal() + "，采购需求数量" + resPurchase.getData().getTotal() + "，工程单位数量" + resSupplier.getData().getTotal());
        return pullRadarSubscriptionReturnDto;
    }

    protected List<OpSubscription> insertSubscription(List<Map<String, Object>> subscriptions, String receiverGUID) {
        List<OpSubscription> opSubscriptions = new LinkedList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        // 如果为空则返回空
        if (subscriptions.size() == 0) {
            return opSubscriptions;
        }

        // 检查这次要插入的订阅在数据库里是否存在
        List<String> waitingData = new LinkedList<>();
        subscriptions.forEach(s -> {
            waitingData.add(s.get("id").toString());
        });

        QueryWrapper<OpSubscription> queryWrapperF = new QueryWrapper<>();
        queryWrapperF.eq("ReceiverGUID", receiverGUID);
        queryWrapperF.in("SubscriptionUID", waitingData);
        List<OpSubscription> existRecord = opSubscriptionDao.selectList(queryWrapperF);

        // 将已经存在的数据准备好用于过滤
        Set<String> existData = new HashSet<>();
        existRecord.forEach(e -> {
            existData.add(e.getSubscriptionUID());
        });

        subscriptions.forEach(f -> {
            if (existData.contains(f.get("id").toString())) {
                return;
            }

            OpSubscription opSubscription = new OpSubscription();
            opSubscription.setOpSubscriptionGUID(UUID.randomUUID());
            opSubscription.setSubscriptionUID(f.get("id").toString());

            opSubscription.setDeveloperName(f.get("developer_name").toString());
            opSubscription.setOrganizingCode(f.get("organizing_code").toString());

            opSubscription.setTitle(f.get("title").toString());
            opSubscription.setReceiverGUID(UUID.fromString(receiverGUID));
            opSubscription.setBiddingServiceCategory(f.get("bidding_service_category").toString());
            opSubscription.setOpportunityCreatedTime(f.get("created_at").toString());
            opSubscription.setSource(f.get("data_source").toString());
            opSubscription.setSourceCode(f.get("data_source_code").toString());
            opSubscription.setTenderee(f.get("ower").toString());
            opSubscription.setTendereeMobile(f.get("ower_mobile").toString());
            opSubscription.setCompanyType(f.get("company_type").toString());
            opSubscription.setPurchaseAmount(f.get("purchase_amount").toString());
            opSubscription.setPhoneType(f.get("phone_type").toString());
            opSubscription.setDeveloperId(f.get("developer_id").toString());
            opSubscription.setDeveloperName(f.get("developer_name").toString());

            try {
                if (f.get("publish_time") != null)
                    opSubscription.setPublishTime(sdf.parse(f.get("publish_time").toString()));
            } catch (java.text.ParseException e) {
            }
            try {
                if (f.get("end_time") != null) opSubscription.setDeadline(sdf.parse(f.get("end_time").toString()));
            } catch (java.text.ParseException e) {
            }

            List<Map<String, String>> projects = (List<Map<String, String>>) f.get("projects");
            if (projects != null && projects.size() > 0) {
                Iterator<Map<String, String>> it = projects.iterator();
                List<String> provinceStr = new LinkedList<>();
                List<String> cityStr = new LinkedList<>();
                List<String> projectStr = new LinkedList<>();
                String cityCodeStr = "";
                String provinceCodeStr = "";
                while (it.hasNext()) {
                    Map<String, String> s = it.next();
                    provinceCodeStr += "[" + s.get("province_code") + "]";
                    cityCodeStr += "[" + s.get("city_code") + "]";
                    projectStr.add(s.get("project_name"));
                    provinceStr.add(s.get("province"));
                    cityStr.add(s.get("city"));
                }
                opSubscription.setCity(String.join(" ", cityStr));
                opSubscription.setProvince(String.join(" ", provinceStr));
                opSubscription.setProjectName(String.join(",", projectStr));
                opSubscription.setProvinceCode(provinceCodeStr);
                opSubscription.setCityCode(cityCodeStr);
            }

            opSubscriptions.add(opSubscription);
        });
        if (opSubscriptions.size() > 0) {
            int insertedRowsCount = opSubscriptionDao.insertBatchWithDynamicExt(opSubscriptions);
            return opSubscriptions;
        }
        return opSubscriptions;
    }

    protected List<ProjectSubscription> insertProjectSubscription(List<Map<String, Object>> subscriptions, String receiverGUID) {
        List<ProjectSubscription> projectSubscriptions = new LinkedList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        if (subscriptions.size() == 0) {
            return projectSubscriptions;
        }

        // 检查这次要插入的订阅在数据库里是否存在
        List<String> waitingData = new LinkedList<>();
        subscriptions.forEach(s -> {
            waitingData.add(s.get("id").toString());
        });

        QueryWrapper<ProjectSubscription> queryWrapperF = new QueryWrapper<>();
        queryWrapperF.eq("ReceiverGUID", receiverGUID);
        queryWrapperF.in("SubscriptionUID", waitingData);
        List<ProjectSubscription> existRecord = projectSubscriptionDao.selectList(queryWrapperF);

        // 将已经存在的数据准备好用于过滤
        Set<String> existData = new HashSet<>();
        existRecord.forEach(e -> {
            existData.add(e.getSubscriptionUID());
        });

        subscriptions.forEach(f -> {
            if (existData.contains(f.get("id").toString())) {
                return;
            }

            ProjectSubscription projectSubscription = new ProjectSubscription();
            projectSubscription.setProjectSubscriptionGUID(UUID.randomUUID());
            projectSubscription.setSubscriptionUID(f.get("id").toString());

            projectSubscription.setDeveloperName(f.get("developer_name").toString());
            projectSubscription.setOrganizingCode(f.get("organizing_code").toString());
            projectSubscription.setDeveloperLogo(f.get("developer_logo").toString());
            projectSubscription.setYcgDeveloperId(f.get("developer_id").toString());

            projectSubscription.setReceiverGUID(UUID.fromString(receiverGUID));
            projectSubscription.setProjectName(f.get("title").toString());
            projectSubscription.setCity(f.get("city").toString());
            projectSubscription.setCityCode(f.get("city_code").toString());
            projectSubscription.setProvince(f.get("province").toString());
            projectSubscription.setProvinceCode(f.get("province_code").toString());
            projectSubscription.setTakeLandPrice(f.get("take_land_price").toString());
            projectSubscription.setLandUnitPrice(f.get("land_unit_price").toString());
            projectSubscription.setLandType(f.get("land_usage_label").toString());
            projectSubscription.setDataType(f.get("source_type").toString());
            projectSubscription.setTakeLandArea(f.get("all_area").toString());
            projectSubscription.setConstructionArea(f.get("construction_area").toString());
            projectSubscription.setConstructionUnit(f.get("construction_unit").toString());
            projectSubscription.setCompanyType(f.get("company_type_label").toString());
            projectSubscription.setHighProjectLabel(f.get("high_project_customers_label").toString());
            projectSubscription.setContractPrice(f.get("contract_price").toString());

            try {
                if (f.get("completed_time") != null) {
                    projectSubscription.setCompletedTime(sdf.parse(f.get("completed_time").toString()));
                }
            } catch (java.text.ParseException e) {
            }
            try {
                if (f.get("start_time") != null) {
                    projectSubscription.setStartTime(sdf.parse(f.get("start_time").toString()));
                }
            } catch (java.text.ParseException e) {
            }
            try {
                if (f.get("take_land_date") != null) {
                    projectSubscription.setTakeLandDate(sdf.parse(f.get("take_land_date").toString()));
                }
            } catch (java.text.ParseException e) {
            }
            try {
                if (f.get("created_at") != null) {
                    projectSubscription.setSourceCreatedTime(sdf.parse(f.get("created_at").toString()));
                }
            } catch (java.text.ParseException e) {
            }

            projectSubscriptions.add(projectSubscription);
        });
        if (projectSubscriptions.size() > 0) {
            int insertedRowsCount = projectSubscriptionDao.insertBatchWithDynamicExt(projectSubscriptions);
            return projectSubscriptions;
        }
        return projectSubscriptions;
    }

    protected boolean sendSubscriptionMessage(InsertSubscriptionReturnDto feeds, SubscriptionConfig config) {
        // 站内信
        String url = pageUtil.getPageUrlBusinessType("商机订阅");
        if (config.getCompanyType() != null && !config.getCompanyType().equals("")) {//判断用户设置了订阅
            MessagePushDTO dto = new MessagePushDTO();
            dto.setUserGuid(config.getCreatedGUID());
            dto.setWakeType("普通消息");
            dto.setWakeSubject("尊敬的用户，今日新增符合商机 " + feeds.getList().size() + "条");
            dto.setAppCode("4022");
            if (!url.equals("")) {
                dto.setPageUrl(url);
            }
            dto.setBusinessGuid(UUID.randomUUID());
            dto.setBusinessType("商机订阅");
            messagePush.sendToDo(dto);
            logUtil.info("商机订阅调度:" + config.getCreatedName(), "站内信发送完成");
        }
        // 邮件
        if (config.getIsEmailSendingOpened() != null && config.getIsEmailSendingOpened().equals(1)) {
            List<String> addresses = new ArrayList<String>() {{
                add(config.getEmail());
            }};
            String htmlContent = "<div>尊敬的用户，今日新增符合商机 " + feeds.getList().size() + " 条 " + "，请及时<a href=\"" + GFYXHost + url + "\">查看</a>！</div>";
            htmlContent += "<ol>";
            Iterator<OpSubscription> itE = feeds.getList().iterator();
            while (itE.hasNext()) {
                //Map<String, Object> s = (Map<String, Object>) itE.next();
                OpSubscription s = itE.next();
                htmlContent += "<li>" + s.getTitle().toString() + "</li>";
            }
            htmlContent += "</ol>";
            //emailHelper.sendEmail(addresses, "商机订阅", htmlContent);
            String sendPushOrder = environment.getProperty("sendmessage.radar_subscription_push_order");
            sendEmail("商机订阅", htmlContent, config.getEmail().toString(), sendPushOrder);
            logUtil.info("商机订阅调度:" + config.getCreatedName(), "邮件发送完成");
        }
        //微信消息
        if (config.getIsWechatSendingOpened() != null && config.getIsWechatSendingOpened().equals(1)) {
            //服务进度
            StringBuilder strT1 = new StringBuilder();
            for (int i = 0; i <= feeds.getList().size() - 1; i++) {
                if (i <= 3) {
                    String value = feeds.getList().get(i).getTitle().toString();
                    strT1.append((MyStringUtil.GetStrNum(value, 14) + "\n").toString());
                }
            }
            //日期
            String strT4 = new SimpleDateFormat("yyyy年MM月dd日").format(new Date()).toString();
            String detailUrl = environment.getProperty("sendmessage.opportunity_direct_url");
            JSONObject content = new JSONObject();
            try {
                content.put("first", "根据您订阅的关键词，为您找到一批商机，快速抓住机会！");
                content.put("T1", "商机订阅");
                content.put("T2", strT1);
                content.put("T3", strT4);
                content.put("T4", "您的订阅设置");
                content.put("url", detailUrl);//详情跳转地址
            } catch (JSONException e) {
                throw new BusinessLogicException("生成json数据异常:" + e.getMessage());
            }
            String sendPushOrder = environment.getProperty("sendmessage.subscription_push_order");
            sendWxMessage(content.toString(), config.getCreatedGUID(), sendPushOrder);
            logUtil.info("商机订阅调度:" + config.getCreatedName(), "微信消息发送完成");
        }

        return true;

    }

    protected boolean sendEmail(String title, String htmlContent, String receiverId, String sendPushOrder) {
        CommonSendPushOrderRequestDto commonSendPushOrderRequestDto = new CommonSendPushOrderRequestDto();
        String tenantCode = contextManager.fetchContextInfo().getTenantCode();
        commonSendPushOrderRequestDto.setTenant_code(tenantCode);
        commonSendPushOrderRequestDto.setPush_order_code(sendPushOrder);//推送单号，存储到nacos
        CommonSendPushOrderRequestDto.SendPushOrderRequestEmail commonSendPushOrderRequestEmail = new CommonSendPushOrderRequestDto.SendPushOrderRequestEmail();
        JSONObject content = new JSONObject();
        try {
            content.put("T1", title);
            content.put("T2", htmlContent);
        } catch (JSONException e) {
            throw new BusinessLogicException("生成json数据异常:" + e.getMessage());
        }
        commonSendPushOrderRequestEmail.setContent(content.toString());
        //接收账号
        ArrayList<String> receiverIds = new ArrayList<>();
        receiverIds.add(receiverId);
        commonSendPushOrderRequestEmail.setReceiver_ids(receiverIds);
        commonSendPushOrderRequestDto.setEmail(commonSendPushOrderRequestEmail);
        //调用发送消息接口
        //emailHelper.sendEmailByYcg(commonSendPushOrderRequestDto);

        SendPushOrderRequestDto sendPushOrderRequestDto = MappingUtil.getSimpleMapperFacade().map(commonSendPushOrderRequestDto, SendPushOrderRequestDto.class);
        YcgApiBaseRespondDto sendRes = opSubscriptionService.sendPushOrder(sendPushOrderRequestDto);
        if (!sendRes.getSuccess()) {
            logUtil.error("调度任务-消息发送", new Exception("发送邮件失败:" + sendRes.getMessage()));
            throw new BusinessLogicException("发送微信消息失败:" + sendRes.getMessage());
        }
        return true;
    }

    protected boolean sendWxMessage(String content, UUID userGUID, String sendPushOrder) {
        SendPushOrderRequestDto sendPushOrderRequestDto = new SendPushOrderRequestDto();
        String tenantCode = contextManager.fetchContextInfo().getTenantCode();
        sendPushOrderRequestDto.setTenant_code(tenantCode);
        sendPushOrderRequestDto.setPush_order_code(sendPushOrder);//推送单号，存储到nacos
        SendPushOrderRequestDto.SendPushOrderRequestWx sendPushOrderRequestWx = new SendPushOrderRequestDto.SendPushOrderRequestWx();
        sendPushOrderRequestWx.setContent(content);
        //获取公众号
        ArrayList<String> receiverId = new ArrayList<>();
        QueryWrapper<UserWxBind> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("UserGUID", userGUID);
        queryWrapper.last("limit 1");
        UserWxBind userWxBind = userWxBindDao.selectOne(queryWrapper);
        if (userWxBind != null && !userWxBind.getOpenId().equals("")) {
            receiverId.add(userWxBind.getOpenId());
        }
        sendPushOrderRequestWx.setReceiver_ids(receiverId);
        sendPushOrderRequestDto.setWx(sendPushOrderRequestWx);
        //调用发送消息接口
        YcgApiBaseRespondDto sendRes = opSubscriptionService.sendPushOrder(sendPushOrderRequestDto);
        if (!sendRes.getSuccess()) {
            logUtil.error("调度任务-消息发送", new Exception("发送微信消息失败:" + sendRes.getMessage()));
            throw new BusinessLogicException("发送微信消息失败:" + sendRes.getMessage());
        }
        return true;
    }

    protected boolean sendProjectSubscriptionMessage(InsertProjectSubscriptionReturnDto feeds, ProjectSubscriptionConfig config) {
        // 站内信
        String url = pageUtil.getPageUrlBusinessType("项目订阅");
        if (config.getLandType() != null && !config.getLandType().equals("")) {//判断用户设置了订阅
            MessagePushDTO dto = new MessagePushDTO();
            dto.setUserGuid(config.getCreatedGUID());
            dto.setWakeType("普通消息");
            dto.setWakeSubject("尊敬的用户，今日新增符合项目 " + feeds.getList().size() + "条");
            dto.setAppCode("4022");

            if (!url.equals("")) {
                dto.setPageUrl(url);
            }
            dto.setBusinessGuid(UUID.randomUUID());
            dto.setBusinessType("项目订阅");
            messagePush.sendToDo(dto);
            logUtil.info("项目订阅调度:" + config.getCreatedName(), "站内信发送完成");
        }
        // 邮件
        if (config.getIsEmailSendingOpened() != null && config.getIsEmailSendingOpened().equals(1)) {
            List<String> addresses = new ArrayList<String>() {{
                add(config.getEmail());
            }};
            String htmlContent = "<div>尊敬的用户，今日新增符合项目 " + feeds.getList().size() + " 条 " + "，请及时<a href=\"" + GFYXHost + url + "\">查看</a>！</div>";
            htmlContent += "<ol>";
            Iterator<ProjectSubscription> itE = feeds.getList().iterator();
            while (itE.hasNext()) {
                ProjectSubscription s = itE.next();
                htmlContent += "<li>" + s.getProjectName().toString() + "</li>";
            }
            htmlContent += "</ol>";
            //emailHelper.sendEmail(addresses, "项目订阅", htmlContent);
            String sendPushOrder = environment.getProperty("sendmessage.subscription_push_order");
            sendEmail("项目订阅", htmlContent, config.getEmail().toString(), sendPushOrder);
            logUtil.info("项目订阅调度:" + config.getCreatedName(), "邮件发送完成");
        }
        //微信消息
        if (config.getIsWechatSendingOpened() != null && config.getIsWechatSendingOpened().equals(1)) {
            //服务进度
            StringBuilder strT1 = new StringBuilder();
            for (int i = 0; i <= feeds.getList().size() - 1; i++) {
                if (i <= 3) {
                    String value = feeds.getList().get(i).getProjectName().toString();
                    strT1.append((MyStringUtil.GetStrNum(value, 14) + "\n").toString());
                }
            }
            //日期
            String strT4 = new SimpleDateFormat("yyyy年MM月dd日").format(new Date()).toString();
            String detailUrl = environment.getProperty("sendmessage.project_direct_url");
            JSONObject content = new JSONObject();
            try {
                content.put("first", "根据您订阅的项目类型，为您找到一批符合项目，快速抓住机会！");
                content.put("T1", "项目订阅");
                content.put("T2", strT1);
                content.put("T3", strT4);
                content.put("T4", "您的订阅设置");
                content.put("url", detailUrl);//详情跳转地址
            } catch (JSONException e) {
                throw new BusinessLogicException("生成json数据异常:" + e.getMessage());
            }
            String sendPushOrder = environment.getProperty("sendmessage.subscription_push_order");
            sendWxMessage(content.toString(), config.getCreatedGUID(), sendPushOrder);
            logUtil.info("项目订阅调度:" + config.getCreatedName(), "微信消息发送完成");
        }
        return true;
    }

    protected boolean sendRadarSubscriptionMessage(PullRadarSubscriptionReturnDto feeds, RadarSubscriptionConfig config) {
        // 1. 定义发送内容
        String url = pageUtil.getPageUrlBusinessType("线索订阅");
        String siteMessage = "尊敬的用户，为您推荐新的机会，包含";
        String emailMessage = "<div>尊敬的用户，为您推荐以下合作机会，请及时<a href=\"" + GFYXHost + url + "\">查看</a>！</div>";
        String wxRemarkMessage = "有新的";
        if (config.getReceivedGUID() == null) {
            logUtil.error("线索订阅调度失败", new BusinessLogicException("ReceivedGUID 为空"));
            return false;
        }
        UUID userId = config.getReceivedGUID();
        UserDTO userInfo = systemDataProvider.getUser(userId.toString());
        if (userInfo == null) {
            logUtil.error("线索订阅调度失败", new BusinessLogicException("用户不存在:" + userId.toString()));
            return false;
        }
        String userName = config.getReceivedName();

        // 判断是否有商机数据
        if (feeds.getPurchaseTotal() > 0) {
            // strT1.append(feeds.getPurchaseTotal()).append("个招标/中标，");
            siteMessage += feeds.getPurchaseTotal() + "招标/中标，";
            emailMessage += "<p>今日新增采购需求" + feeds.getPurchaseTotal() + "条</p>";
            wxRemarkMessage += feeds.getPurchaseTotal() + "个招标/中标，";
        }
        // 判断是否有土地数据
        if (feeds.getLandTotal() > 0) {
            siteMessage += feeds.getLandTotal() + "个土地交易，";
            emailMessage += "<p>今日新增土地交易" + feeds.getLandTotal() + "个</p>";
            wxRemarkMessage += feeds.getLandTotal() + "个土地，";
        }
        // 判断是否有项目数据
        if (feeds.getMohurdProjectTotal() > 0) {
            siteMessage += feeds.getMohurdProjectTotal() + "个在建项目，";
            emailMessage += "<p>今日新增在建项目" + feeds.getMohurdProjectTotal() + "个</p>";
            wxRemarkMessage += feeds.getMohurdProjectTotal() + "个在建，";
        }
        // 判断是否有开盘数据
        if (feeds.getProjectTotal() > 0) {
            siteMessage += feeds.getProjectTotal() + "个在售项目，";
            emailMessage += "<p>今日新增在售项目" + feeds.getProjectTotal() + "个</p>";
            wxRemarkMessage += feeds.getProjectTotal() + "个开盘，";
        }
        // 判断是否有工程单位
        if (feeds.getSupplierTotal() > 0) {
            siteMessage += feeds.getSupplierTotal() + "家工程单位，";
            emailMessage += "<p>今日新增工程单位" + feeds.getSupplierTotal() + "家</p>";
            wxRemarkMessage += feeds.getSupplierTotal() + "家工程单位，";
        }

        // 2 发送站内信
        if (config.getUserHasSetting() != null && config.getUserHasSetting().equals(1)) {
            MessagePushDTO dto = new MessagePushDTO();
            dto.setUserGuid(userId);
            dto.setWakeType("订阅消息");
            siteMessage = siteMessage.substring(0, siteMessage.length() - 1);
            dto.setWakeSubject(siteMessage);
            dto.setAppCode("4022");
            if (!url.equals("")) {
                dto.setPageUrl(url);
            }
            dto.setBusinessGuid(UUID.randomUUID());
            dto.setBusinessType("线索订阅");
            messagePush.sendToDo(dto);
            logUtil.info("线索订阅调度:" + userName, "站内信发送完成");
        }

        // 3 邮件发送
        if (config.getEmail() != null && !config.getEmail().equals("")) {
            List<String> addresses = new ArrayList<String>() {{
                add(config.getEmail());
            }};
            //emailHelper.sendEmail(addresses, "项目订阅", htmlContent);
            String sendPushOrder = environment.getProperty("sendmessage.radar_subscription_push_order");
            sendEmail("线索订阅", emailMessage, config.getEmail().toString(), sendPushOrder);
            logUtil.info("线索订阅调度:" + userName, "邮件发送完成");
        }

        // 4 发送微信消息
        if (config.getIsWechatSendingOpened() != null && config.getIsWechatSendingOpened().equals(1)) {
            //服务进度
            wxRemarkMessage = wxRemarkMessage.substring(0, wxRemarkMessage.length() - 1);
            //日期
            String strT4 = new SimpleDateFormat("yyyy年MM月dd日").format(new Date()).toString();
            String detailUrl = environment.getProperty("sendmessage.radar_direct_url");
            if (feeds.getPurchaseTotal() > 0) {
                detailUrl = environment.getProperty("sendmessage.radar_direct_purchase_url");
            } else if (feeds.getLandTotal() > 0 || feeds.getProjectTotal() > 0 || feeds.getMohurdProjectTotal() > 0) {
                detailUrl = environment.getProperty("sendmessage.radar_direct_project_url");
            } else if (feeds.getSupplierTotal() > 0) {
                detailUrl = environment.getProperty("sendmessage.radar_direct_supplier_url");
            }
            JSONObject content = new JSONObject();
            // 获取用户信息名称
            String strT5 = "订阅通知";
            String mobile = "";
            String newUserName = "";
            strT5 = "【" + userInfo.getUserName() + "】订阅通知";
            newUserName = userInfo.getUserName();
            mobile = userInfo.getCellphone();
            try {
                content.put("T1", "新线索通知");
                content.put("T2", wxRemarkMessage);
                content.put("T3", strT4);
                content.put("T4", strT5);
                content.put("T5", wxRemarkMessage);
                content.put("url", detailUrl);//详情跳转地址
            } catch (JSONException e) {
                throw new BusinessLogicException("生成json数据异常:" + e.getMessage());
            }
            // 记录推送日志 todo 消息中心回调配置和接收回调改状态
            writeSubscriptionPushLog(feeds, mobile, newUserName, userId);
            String sendPushOrder = environment.getProperty("sendmessage.radar_subscription_push_order");
            sendWxMessage(content.toString(), userId, sendPushOrder);
            logUtil.info("线索订阅调度:" + userName, "微信消息发送完成");
        }
        return true;
    }

    // 记录推送日志
    protected boolean writeSubscriptionPushLog(PullRadarSubscriptionReturnDto feeds, String mobile, String userName, UUID userId) {
        RadarSubscriptionPushLog radarSubscriptionPushLog = new RadarSubscriptionPushLog();
        radarSubscriptionPushLog.setLandTotal(feeds.getLandTotal());
        radarSubscriptionPushLog.setProjectTotal(feeds.getProjectTotal());
        radarSubscriptionPushLog.setPurchaseTotal(feeds.getPurchaseTotal());
        radarSubscriptionPushLog.setMohurdProjectTotal(feeds.getMohurdProjectTotal());
        radarSubscriptionPushLog.setSupplierTotal(feeds.getSupplierTotal());
        radarSubscriptionPushLog.setMobile(mobile);
        radarSubscriptionPushLog.setUserName(userName);
        radarSubscriptionPushLog.setUserGUID(userId);
        radarSubscriptionPushLog.setCreatedTime(new Date());

        // 目前写成回调成功的状态，todo 调用消息中心回调接口
        radarSubscriptionPushLog.setIsSuccess(1);
        radarSubscriptionPushLog.setCallBackTime(new Date());
        try {
            logUtil.info("记录雷达推送日志info", radarSubscriptionPushLog.toString());
            radarSubscriptionPushLogDao.insert(radarSubscriptionPushLog);
            return true;
        } catch (Exception e) {
            logUtil.error("记录雷达推送日志", e);
        }
        return false;
    }

    public FieldsSetting loadMySubscriptionFields() {
        //硬编码的获取字段逻辑
        FieldsSetting fieldsSetting = new FieldsSetting();
        fieldsSetting.setIdField("opSubscriptionGUID");
        fieldsSetting.setFields(new ArrayList<>());
        String groupName = "my_subscription";

        fieldsSetting.getFields().add(new DataApiField("biddingServiceCategory", groupName, "服务分类", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("city", groupName, "城市", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("cityCode", groupName, "城市Code", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("createdTime", groupName, "创建时间", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("deadline", groupName, "截止日期", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("deadlineStr", groupName, "截止日期格式化", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("developerName", groupName, "开发商名称", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("modifiedTime", groupName, "编辑时间", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("opSubscriptionGUID", groupName, "ID", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("opportunityCreatedTime", groupName, "商机创建时间", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("organizingCode", groupName, "信用代码", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("projectName", groupName, "项目名称", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("province", groupName, "省份", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("provinceCode", groupName, "省份编码", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("publishTime", groupName, "发布时间", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("publishTimeStr", groupName, "发布日期格式化", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("source", groupName, "信息来源", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("sourceCode", groupName, "信息来源Code", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("subscriptionUID", groupName, "商机订阅ID", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("tenderee", groupName, "招标负责人", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("tendereeMobile", groupName, "招标负责人电话", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("title", groupName, "商机名称", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("applyStatus", groupName, "报名状态", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("companyType", groupName, "企业类型", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("phoneType", groupName, "联系方式", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("purchaseAmount", groupName, "采购预算", FieldType.String));

        // 返回
        return fieldsSetting;
    }

    public FieldsSetting loadProjectSubscriptionFields() {
        //硬编码的获取字段逻辑
        FieldsSetting fieldsSetting = new FieldsSetting();
        fieldsSetting.setIdField("projectSubscriptionGUID");
        fieldsSetting.setFields(new ArrayList<>());
        String groupName = "project_subscription";

        fieldsSetting.getFields().add(new DataApiField("city", groupName, "城市", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("cityCode", groupName, "城市Code", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("createdTime", groupName, "创建时间", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("developerLogo", groupName, "开发商Logo", FieldType.Picture));
        fieldsSetting.getFields().add(new DataApiField("developerName", groupName, "开发商名称", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("modifiedTime", groupName, "编辑时间", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("opSubscriptionGUID", groupName, "ID", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("organizingCode", groupName, "信用代码", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("projectName", groupName, "项目名称", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("province", groupName, "省份", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("provinceCode", groupName, "省份编码", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("source", groupName, "信息来源", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("sourceCode", groupName, "信息来源Code", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("subscriptionUID", groupName, "商机订阅ID", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("dataType", groupName, "数据类型", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("companyType", groupName, "公司类型", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("landType", groupName, "土地类型", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("startTime", groupName, "开工日期", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("completedTime", groupName, "竣工日期", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("constructionArea", groupName, "施工面积", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("constructionUnit", groupName, "施工单位", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("contractPrice", groupName, "合同金额(万元)", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("takeLandArea", groupName, "土地面积", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("takeLandDate", groupName, "成交日期", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("takeLandPrice", groupName, "成交价格(万元)", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("landUnitPrice", groupName, "楼面单价", FieldType.String));
        fieldsSetting.getFields().add(new DataApiField("id", groupName, "详情页ID", FieldType.String));


        // 返回
        return fieldsSetting;
    }

    public ListDataResult loadMySubscriptionData(LoadDataParams options) {
        // 分页
        optionsProcess(options);
        options.setSortField("publishTime");
        options.setSortOrder("DESC");
        Page<OpSubscription> page = ExtensionLoadDataHelper.getPage(options);
        QueryWrapper<OpSubscription> query = ExtensionLoadDataHelper.warp(OpSubscription.class, options);
        // 查询
        IPage<OpSubscription> roomPage = opSubscriptionDao.selectPage(page, query);
        ListDataResult result = new ListDataResult();
        List<OpSubscriptionLoadDataApiExtDto> opSubscriptions = MappingUtil.getSimpleMapperFacade().mapAsList(roomPage.getRecords(), OpSubscriptionLoadDataApiExtDto.class);
        opSubscriptions.forEach(o -> {
            Date now = new Date();
            if (o.getDeadline() == null) {
                o.setApplyStatus("未知");
            } else {
                String applyStatus = o.getDeadline().getTime() > now.getTime() ? "报名中" : "已截止";
                o.setApplyStatus(applyStatus);
            }

            String tenderee = (o.getTenderee() == null || o.getTenderee().equals("")) ? "--" : o.getTenderee().substring(0, 1) + "**";
            o.setTenderee(tenderee);
            boolean hideMobile = o.getTendereeMobile() == null || o.getTendereeMobile().equals("") || o.getSourceCode().equals("ycg_bid") || o.getSourceCode().equals("ycg_recruit");
            String tendereeMobile = hideMobile ? "--" : "添加线索后，进入线索管理查看";
            o.setTendereeMobile(tendereeMobile);

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (o.getPublishTime() != null) o.setPublishTimeStr(sdf.format(o.getPublishTime()));
            if (o.getDeadline() != null) o.setDeadlineStr(sdf.format(o.getDeadline()));
        });
        result.setData(opSubscriptions);
        result.setTotal((int) roomPage.getTotal());
        return result;
    }

    public ListDataResult loadMySubscriptionDataBySql(LoadDataParams options) {
        // 分页
        optionsProcessBySql(options);
        OpSubscriptionRequestDto dto = new OpSubscriptionRequestDto();
        dto.setPage(options.getPageIndex() + 1);
        dto.setPageSize(options.getPageSize());
        dto.addFilterByLoadDataApi(options.getOptions().getFilters());
        dto.setOffset(options.getPageIndex() * dto.getPageSize());
        if (options.getPageIndex() == -1) {//如果是导出全部数据，pageIndex=-1，此时不做limit操作
            dto.setIsNeedLimit(0);
        }
        if (dto.getPurchaseAmountMin() != null) {
            dto.setPurchaseAmountMin(dto.getPurchaseAmountMin() * 10000);
        }
        if (dto.getPurchaseAmountMax() != null) {
            dto.setPurchaseAmountMax(dto.getPurchaseAmountMax() * 10000);
        }

        // 查询
        TotalDto total = opSubscriptionDao.queryOpSubscriptionTotal(dto);
        List<OpSubscriptionDataDto> res = opSubscriptionDao.queryOpSubscriptionData(dto);

        ListDataResult result = new ListDataResult();
        List<OpSubscriptionLoadDataApiExtDto> opSubscriptions = MappingUtil.getSimpleMapperFacade().mapAsList(res, OpSubscriptionLoadDataApiExtDto.class);
        opSubscriptions.forEach(o -> {
            Date now = new Date();
            if (o.getDeadline() == null) {
                o.setApplyStatus("未知");
            } else {
                String applyStatus = o.getDeadline().getTime() > now.getTime() ? "报名中" : "已截止";
                o.setApplyStatus(applyStatus);
            }

            String tenderee = (o.getTenderee() == null || o.getTenderee().equals("")) ? "--" : o.getTenderee().substring(0, 1) + "**";
            o.setTenderee(tenderee);

            String tendereeMobileMp = (o.getTendereeMobile() != null && !o.getTendereeMobile().equals("") && o.getTendereeMobile().length() > 7) ? o.getTendereeMobile().substring(0, 3) + "****" + o.getTendereeMobile().substring(7) : o.getTendereeMobile();
            o.setTendereeMobileMp(tendereeMobileMp);

            boolean hideMobile = o.getTendereeMobile() == null || o.getTendereeMobile().equals("") || o.getSourceCode().equals("ycg_bid") || o.getSourceCode().equals("ycg_recruit");
            String tendereeMobile = hideMobile ? "--" : "添加线索后，进入线索管理查看";
            o.setTendereeMobile(tendereeMobile);

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            if (o.getPublishTime() != null) o.setPublishTimeStr(sdf.format(o.getPublishTime()));
            if (o.getDeadline() != null) o.setDeadlineStr(sdf.format(o.getDeadline()));
        });
        result.setData(opSubscriptions);
        result.setTotal((int) total.getTotal());
        return result;
    }

    public ListDataResult loadProjectSubscriptionData(LoadDataParams options) {
        // 分页
        optionsProcessProject(options);
        ProjectSubscriptionRequestDto dto = new ProjectSubscriptionRequestDto();
        dto.setPage(options.getPageIndex() + 1);
        dto.setPageSize(options.getPageSize());
        dto.addFilterByLoadDataApi(options.getOptions().getFilters());
        dto.setOffset(options.getPageIndex() * dto.getPageSize());
        if (options.getPageIndex() == -1) {//如果是导出全部数据，pageIndex=-1，此时不做limit操作
            dto.setIsNeedLimit(0);
        }
        if (dto.getProvinceCode() != null && dto.getProvinceCode().equals("0")) {
            dto.setProvinceCode("");
        }
        //获取项目订阅数据
        TotalDto total = projectSubscriptionDao.queryProjectSubscriptionTotal(dto);
        List<ProjectSubscriptionDataDto> res = projectSubscriptionDao.queryProjectSubscriptionData(dto);

        ListDataResult result = new ListDataResult();
        res.forEach(o -> {
            o.setDeveloperLogo(ycgFileService.getEnterpriseLogo(o.getYcgDeveloperId(), o.getDeveloperLogo()));
            String id = o.getSubscriptionUID().replace("work_", "").toString();
            id = id.replace("land_", "").toString();
            o.setId(id);
            //时间格式化
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            if (o.getTakeLandDate() != null) {
                try {
                    o.setTakeLandDate(sdf.format(sdf.parse(o.getTakeLandDate())));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            if (o.getStartTime() != null) {
                try {
                    o.setStartTime(sdf.format(sdf.parse(o.getStartTime())));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            if (o.getCompletedTime() != null) {
                try {
                    o.setCompletedTime(sdf.format(sdf.parse(o.getCompletedTime())));
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }

        });
        result.setData(res);
        result.setTotal((int) total.getTotal());
        return result;
    }

    protected void optionsProcess(LoadDataParams options) {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        loadDataApiServiceHelper.addOneOptionFilter(options, "receiverGUID", "eq", authenticationUser.getUserId().toString());
        options.getOptions().getFilters().forEach(f -> {
            f.getCondition().forEach(c -> {
                if (c.getField().equals("cityCode")) {
                    c.setOperatorType("like");
                    c.setValue("[" + c.getValue() + "]");
                }
                if (c.getField().equals("provinceCode")) {
                    c.setOperatorType("like");
                    c.setValue("[" + c.getValue() + "]");
                }
                if (c.getField().equals("applyStatus")) {
                    c.setField("deadline");
                    if (c.getValue().equals("报名中")) {
                        c.setOperatorType("ge");
                    } else {
                        c.setOperatorType("lt");
                    }
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    c.setValue(sdf.format(new Date()));
                }
            });
        });
    }

    protected void optionsProcessProject(LoadDataParams options) {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        loadDataApiServiceHelper.addOneOptionFilter(options, "receiverGUID", "eq", authenticationUser.getUserId().toString());
    }

    protected void optionsProcessBySql(LoadDataParams options) {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        loadDataApiServiceHelper.addOneOptionFilter(options, "receiverGUID", "eq", authenticationUser.getUserId().toString());
        options.getOptions().getFilters().forEach(f -> {
            f.getCondition().forEach(c -> {
                if (c.getField().equals("cityCode")) {
                    c.setOperatorType("like");
                    c.setValue("[" + c.getValue() + "]");
                }
                if (c.getField().equals("provinceCode")) {
                    c.setOperatorType("like");
                    if (c.getValue().equals("0")) {
                        c.setValue("");
                    } else {
                        c.setValue("[" + c.getValue() + "]");
                    }

                }

            });
        });
    }

    public Object getMySubscription(SubscriptionType type) {
        Object res;
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        switch (type) {
            case CustomerFeed:
                QueryWrapper<FeedConfig> queryWrapperF = new QueryWrapper<>();
                queryWrapperF.eq("CreatedGUID", authenticationUser.getUserId());
                queryWrapperF.last("limit 1");
                FeedConfig feedConfig = feedConfigDao.selectOne(queryWrapperF);
                if (feedConfig != null) {
                    feedConfig.setLandArea(this.filterProvinceProfit(feedConfig.getLandArea()));
                    feedConfig.setProjectArea(this.filterProvinceProfit(feedConfig.getProjectArea()));
                }
                res = feedConfig;
                break;
            case Subscription:
                QueryWrapper<SubscriptionConfig> queryWrapperS = new QueryWrapper<>();
                queryWrapperS.eq("CreatedGUID", authenticationUser.getUserId());
                queryWrapperS.last("limit 1");
                SubscriptionConfig subscriptionConfig = subscriptionConfigDao.selectOne(queryWrapperS);
                if (subscriptionConfig != null) {
                    subscriptionConfig.setArea(this.filterProvinceProfit(subscriptionConfig.getArea()));
                }
                res = subscriptionConfig;
                break;
            case ProjectSubscription:
                QueryWrapper<ProjectSubscriptionConfig> queryWrapperP = new QueryWrapper<>();
                queryWrapperP.eq("CreatedGUID", authenticationUser.getUserId());
                queryWrapperP.last("limit 1");
                ProjectSubscriptionConfig projectSubscriptionConfig = projectSubscriptionConfigDao.selectOne(queryWrapperP);
                if (projectSubscriptionConfig != null) {
                    projectSubscriptionConfig.setArea(this.filterProvinceProfit(projectSubscriptionConfig.getArea()));
                }
                res = projectSubscriptionConfig;
                break;
            case RadarSubscription:
                QueryWrapper<RadarSubscriptionConfig> queryWrapperR = new QueryWrapper<>();
                queryWrapperR.eq("ReceivedGUID", authenticationUser.getUserId());
                queryWrapperR.last("limit 1");
                RadarSubscriptionConfig radarSubscriptionConfig = radarSubscriptionConfigDao.selectOne(queryWrapperR);
                if (radarSubscriptionConfig != null) {
                    radarSubscriptionConfig.setArea(this.filterProvinceProfit(radarSubscriptionConfig.getArea()));
                    //承接部分管理员的配置
                    if (radarSubscriptionConfig.getUserHasSetting() == null) {
                        QueryWrapper<RadarSubscriptionConfig> adminWrapperR = new QueryWrapper<>();
                        adminWrapperR.eq("ReceivedGUID", SubscriptionService.ADMIN_GUID);//管理员
                        RadarSubscriptionConfig adminSubscriptionConfig = radarSubscriptionConfigDao.selectOne(adminWrapperR);
                        if (adminSubscriptionConfig != null && adminSubscriptionConfig.getUserHasSetting() != null) {
                            radarSubscriptionConfig.setLandUsage(adminSubscriptionConfig.getLandUsage());
                            radarSubscriptionConfig.setProjectType(adminSubscriptionConfig.getProjectType());
                            radarSubscriptionConfig.setProjectTag(adminSubscriptionConfig.getProjectTag());
                            radarSubscriptionConfig.setFitmentType(adminSubscriptionConfig.getFitmentType());
                            radarSubscriptionConfig.setSupplierKeywords(adminSubscriptionConfig.getSupplierKeywords());
                            radarSubscriptionConfig.setBidKeywords(adminSubscriptionConfig.getBidKeywords());
                            radarSubscriptionConfig.setProjectKeywords(adminSubscriptionConfig.getProjectKeywords());
                        }
                    }
                }
                res = radarSubscriptionConfig;
                break;
            default:
                throw new BusinessLogicException("你传的数字不正确");
        }

        return res;
    }


    public boolean isSetAdminSubscription() {
        GetUsersRequestDto getUsersRequestDto = new GetUsersRequestDto();
        //getUsersRequestDto.setKeyword("超级管理员");
        getUsersRequestDto.setIsAdmin(true);
        List<UserDTO> userDTOS = remoteSystemService.GetUsers(getUsersRequestDto);

        if (userDTOS.size() != 1) {
            throw new BusinessLogicException("您的超级管理员数量有问题，为零或者大于一");
        }

        UserDTO userDTO = userDTOS.get(0);

        QueryWrapper<SubscriptionConfig> queryWrapperS = new QueryWrapper<>();
        queryWrapperS.eq("SubscriptionConfigGUID", userDTO.getGuid());
        queryWrapperS.last("limit 1");
        SubscriptionConfig subscriptionConfig = subscriptionConfigDao.selectOne(queryWrapperS);
        if (subscriptionConfig != null && subscriptionConfig.getKeyword() != null && subscriptionConfig.getKeyword().length() > 0) {
            return true;
        }
        return false;
    }

    public QrCodeDataDto getWxQrCode() {
        String tenantCode = contextManager.fetchContextInfo().getTenantCode();
        String sceneId = "supplier_saas_" + tenantCode + "_" + System.currentTimeMillis();

        QrCodeDataDto qrCodeData = new QrCodeDataDto();
        GenerateQrCodeRequestDto qrCodeRequestDto = new GenerateQrCodeRequestDto();
        qrCodeRequestDto.setScene_id(sceneId);
        YcgApiBaseRespondDto qrCodeRes = opSubscriptionService.generateQrCode(qrCodeRequestDto);
        if (qrCodeRes.getSuccess()) {
            if (qrCodeRes.getData().get("qr_code_url").toString().equals("")) {
                logUtil.error("云采购公众号", new BusinessLogicException("获取公众号二维码失败"));
            }
            qrCodeData.setQrCodeUrl(qrCodeRes.getData().get("qr_code_url").toString());
            if (!qrCodeRes.getData().get("scene_id").equals("")) {
                qrCodeData.setSceneId(qrCodeRes.getData().get("scene_id").toString());
            }
        } else {
            logUtil.error("云采购公众号", new BusinessLogicException("获取公众号二维码失败"));
        }
        return qrCodeData;
    }

    public QrCodeDataDto getBindStatus(GetWxQrCodeRequestDto getWxQrCodeRequestDto) {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        String sceneId = getWxQrCodeRequestDto.getSceneId();
        if (getWxQrCodeRequestDto.getSceneId() != null && getWxQrCodeRequestDto.getSceneId().equals("")) {
            throw new BusinessLogicException("缺少sceneId参数");
        }

        //绑定openid
        QrCodeDataDto qrCodeData = new QrCodeDataDto();
        QueryWrapper<UserWxBind> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("UserGUID", authenticationUser.getUserId());
        YcgApiBaseRespondDto followStatus = opSubscriptionService.getFollowStatus(sceneId);
        queryWrapper.last("limit 1");
        UserWxBind userWxBind = userWxBindDao.selectOne(queryWrapper);
        if (followStatus.getData() != null && !followStatus.getData().get("open_id").equals("")) {
            qrCodeData.setSceneOpenId(followStatus.getData().get("open_id").toString());
            if (userWxBind == null) {
                userWxBind = new UserWxBind();
                userWxBind.setUserGUID(authenticationUser.getUserId());
                userWxBind.setMobile(authenticationUser.getMobilePhone());
                userWxBind.setOpenId(followStatus.getData().get("open_id").toString());
                userWxBindDao.insert(userWxBind);
            } else {
                userWxBind.setOpenId(followStatus.getData().get("open_id").toString());
                userWxBindDao.updateById(userWxBind);
            }
        }
        qrCodeData.setSceneId(sceneId);

        //查询公众号关注状态
        if (userWxBind != null && userWxBind.getOpenId() != null) {
            YcgApiBaseRespondDto openIdData = opSubscriptionService.getFollowByOpenid(userWxBind.getOpenId());
            if (openIdData.getSuccess()) {
                if (openIdData.getData() != null && !openIdData.getData().get("openid").equals("")) {
                    qrCodeData.setAttentionStatus(1);
                    qrCodeData.setOpenId(openIdData.getData().get("openid").toString());
                }
            } else {
                logUtil.error("云采购公众号绑定状态", new BusinessLogicException("接口返回异常"));
            }

        }
        return qrCodeData;
    }


    public Boolean addSubscription(AddSubscriptionRequestDto dto) {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        dto.setCreatedGUID(authenticationUser.getUserId());
        QueryWrapper<SubscriptionConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("CreatedGUID", authenticationUser.getUserId());
        queryWrapper.last("limit 1");
        SubscriptionConfig subscriptionConfig = subscriptionConfigDao.selectOne(queryWrapper);

        if (subscriptionConfig == null) {
            subscriptionConfig = new SubscriptionConfig();
            subscriptionConfig.setSubscriptionConfigGUID(UUID.randomUUID());
            subscriptionConfig = MappingUtil.getSimpleMapperFacade().map(dto, SubscriptionConfig.class);
            subscriptionConfigDao.insert(subscriptionConfig);
        } else {
            subscriptionConfig = MappingUtil.getSimpleMapperFacade().map(dto, SubscriptionConfig.class);
            subscriptionConfigDao.updateById(subscriptionConfig);
        }
        return true;
    }

    public Boolean addProjectSubscription(AddProjectSubscriptionRequestDto dto) {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        QueryWrapper<ProjectSubscriptionConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("CreatedGUID", authenticationUser.getUserId());
        queryWrapper.last("limit 1");
        ProjectSubscriptionConfig projectSubscriptionConfig = projectSubscriptionConfigDao.selectOne(queryWrapper);
        if (projectSubscriptionConfig == null) {
            projectSubscriptionConfig = new ProjectSubscriptionConfig();
            projectSubscriptionConfig.setProjectSubscriptionConfigGUID(UUID.randomUUID());
            projectSubscriptionConfig = MappingUtil.getSimpleMapperFacade().map(dto, ProjectSubscriptionConfig.class);
            projectSubscriptionConfigDao.insert(projectSubscriptionConfig);
        } else {
            projectSubscriptionConfig = MappingUtil.getSimpleMapperFacade().map(dto, ProjectSubscriptionConfig.class);
            if (projectSubscriptionConfig.getLandPriceMax() == null || projectSubscriptionConfig.getLandPriceMax().equals("")) {
                projectSubscriptionConfig.setLandPriceMax("0");
            }
            if (projectSubscriptionConfig.getLandPriceMin() == null || projectSubscriptionConfig.getLandPriceMin().equals("")) {
                projectSubscriptionConfig.setLandPriceMin("0");
            }
            projectSubscriptionConfigDao.updateById(projectSubscriptionConfig);
        }
        return true;
    }

    public Boolean addRadarSubscription(AddRadarSubscriptionRequestDto dto) {
        try {
            User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
            QueryWrapper<RadarSubscriptionConfig> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("ReceivedGUID", authenticationUser.getUserId());
            queryWrapper.last("limit 1");
            RadarSubscriptionConfig radarSubscriptionConfig = radarSubscriptionConfigDao.selectOne(queryWrapper);
            boolean isNewRecord = false;
            if (radarSubscriptionConfig == null) {
                isNewRecord = true;
                radarSubscriptionConfig = new RadarSubscriptionConfig();
                radarSubscriptionConfig.setRadarSubscriptionConfigGUID(authenticationUser.getUserId());
                radarSubscriptionConfig.setReceivedGUID(authenticationUser.getUserId());
                radarSubscriptionConfig.setReceivedName(authenticationUser.getUserName());
            }
            radarSubscriptionConfig.setArea(dto.getArea());
            radarSubscriptionConfig.setEmail(dto.getEmail());
            radarSubscriptionConfig.setBidKeywords(dto.getBidKeywords());
            radarSubscriptionConfig.setFitmentType(dto.getFitmentType());
            radarSubscriptionConfig.setLandUsage(dto.getLandUsage());
            radarSubscriptionConfig.setPeriod(dto.getPeriod());
            radarSubscriptionConfig.setProjectTag(dto.getProjectTag());
            radarSubscriptionConfig.setProjectType(dto.getProjectType());
            radarSubscriptionConfig.setSendingTime(dto.getSendingTime());
            radarSubscriptionConfig.setUserHasSetting(dto.getUserHasSetting());
            radarSubscriptionConfig.setIsWechatSendingOpened(dto.getIsWechatSendingOpened());
            radarSubscriptionConfig.setSupplierKeywords(dto.getSupplierKeywords());
            radarSubscriptionConfig.setProjectKeywords(dto.getProjectKeywords());
            if (radarSubscriptionConfig.getPeriod().equals("")) {
                radarSubscriptionConfig.setPeriod(PERIOD_DAILY);
            }
            if (radarSubscriptionConfig.getSendingTime().equals("")) {
                radarSubscriptionConfig.setSendingTime(SEND_TIME_EIGHT);
            }
            if (isNewRecord) {
                radarSubscriptionConfigDao.insert(radarSubscriptionConfig);
            } else {
                int updateRow = radarSubscriptionConfigDao.updateById(radarSubscriptionConfig);
                logUtil.info("保存线索订阅", "更新" + updateRow + "条数据");
            }
            return true;
        } catch (Exception e) {
            logUtil.error("保存线索订阅", e);
        }
        return true;
    }

    /**
     * 同步订阅
     *
     * @param type
     * @return
     */
    public Boolean syncSubscription(SubscriptionType type) {
        User authenticationUser = ThreadContextHolder.getInstance().get(AuthenticationUser.class);
        switch (type) {
            case CustomerFeed:
            case Subscription:
            case ProjectSubscription:
                break;
            case RadarSubscription:
                if (authenticationUser.getUserId().equals(SubscriptionService.ADMIN_GUID)) {
                    QueryWrapper<RadarSubscriptionConfig> queryWrapperR = new QueryWrapper<>();
                    queryWrapperR.eq("ReceivedGUID", authenticationUser.getUserId());
                    queryWrapperR.last("limit 1");
                    RadarSubscriptionConfig adminSubscription = radarSubscriptionConfigDao.selectOne(queryWrapperR);
                    if (adminSubscription != null && adminSubscription.getUserHasSetting().equals(1)) {
                        //1、数据库中存在的用户，但是没有保存订阅
                        RadarSubscriptionConfig updateData = new RadarSubscriptionConfig();
                        updateData.setLandUsage(adminSubscription.getLandUsage());
                        updateData.setProjectType(adminSubscription.getProjectType());
                        updateData.setFitmentType(adminSubscription.getFitmentType());
                        updateData.setProjectTag(adminSubscription.getProjectTag());
                        updateData.setBidKeywords(adminSubscription.getBidKeywords());
                        updateData.setSupplierKeywords(adminSubscription.getSupplierKeywords());
                        updateData.setProjectKeywords(adminSubscription.getProjectKeywords());
                        updateData.setModifiedGUID(authenticationUser.getUserId());
                        updateData.setModifiedName(authenticationUser.getUserName());
                        QueryWrapper<RadarSubscriptionConfig> updateWrapper = new QueryWrapper<>();
                        updateWrapper.isNull("UserHasSetting");
                        int updateRows = radarSubscriptionConfigDao.update(updateData, updateWrapper);
                        logUtil.info("同步订阅配置", "已同步订阅配置" + updateRows + "条");
                        //2、不在数据库中的用户
                        ArrayList<UUID> userList = new ArrayList<>();
                        List<RadarSubscriptionConfig> existSubscription = radarSubscriptionConfigDao.selectList(new QueryWrapper<>());
                        existSubscription.forEach(p -> {
                            userList.add(p.getReceivedGUID());
                        });
                        List<UserDTO> allUser = remoteSystemService.GetAllUsers(new SystemGetUserRequestDto());
                        List<RadarSubscriptionConfig> radarSubscription = new LinkedList<>();
                        allUser.forEach(u -> {
                            if (!userList.contains(UUID.fromString(u.getGuid()))) {
                                RadarSubscriptionConfig radarSubscriptionConfig = new RadarSubscriptionConfig();
                                radarSubscriptionConfig.setLandUsage(adminSubscription.getLandUsage());
                                radarSubscriptionConfig.setProjectType(adminSubscription.getProjectType());
                                radarSubscriptionConfig.setFitmentType(adminSubscription.getFitmentType());
                                radarSubscriptionConfig.setProjectTag(adminSubscription.getProjectTag());
                                radarSubscriptionConfig.setBidKeywords(adminSubscription.getBidKeywords());
                                radarSubscriptionConfig.setSupplierKeywords(adminSubscription.getSupplierKeywords());
                                radarSubscriptionConfig.setProjectKeywords(adminSubscription.getProjectKeywords());
                                radarSubscriptionConfig.setReceivedGUID(UUID.fromString(u.getGuid()));
                                radarSubscriptionConfig.setReceivedName(u.getUserName());
                                radarSubscriptionConfig.setRadarSubscriptionConfigGUID(UUID.fromString(u.getGuid()));
                                radarSubscription.add(radarSubscriptionConfig);
                            }
                        });
                        if (radarSubscription.size() > 0) {
                            radarSubscriptionConfigDao.insertBatchWithDynamicExt(radarSubscription);
                        }

                    } else {
                        logUtil.info("同步订阅配置", "当前管理员尚未设置订阅，无法同步");
                        throw new BusinessLogicException("当前管理员尚未设置订阅，无法同步");
                    }
                } else {
                    logUtil.info("同步订阅配置", "只有管理员账户才能同步订阅配置");
                    throw new BusinessLogicException("只有管理员账户才能同步订阅配置");
                }
                break;
            default:
                throw new BusinessLogicException("你传的数字不正确");
        }

        return true;
    }
}
